<?php

namespace App\Filament\Pages\Settings;

use App\Enums\NavigationGroup;
use App\Enums\SystemConfig;
use App\Models\SystemConfig as SystemConfigModel;
use App\Services\SystemConfigService;
use Filament\Actions\Action;
use Filament\Actions\Concerns\InteractsWithActions;
use Filament\Actions\Contracts\HasActions;
use Filament\Actions\CreateAction;
use Filament\Forms\Components\Radio;
use Filament\Forms\Components\Select;
use Filament\Forms\Components\Textarea;
use Filament\Forms\Components\TextInput;
use Filament\Forms\Concerns\InteractsWithForms;
use Filament\Forms\Contracts\HasForms;
use Filament\Notifications\Notification;
use Filament\Pages\Page;
use Filament\Schemas\Components\Tabs;
use Filament\Schemas\Components\Tabs\Tab;
use Illuminate\Support\Collection;

class Setting extends Page implements HasActions, HasForms
{
    use InteractsWithActions;
    use InteractsWithForms;

    public static string|null|\UnitEnum $navigationGroup = NavigationGroup::Settings;

    public static ?string $navigationLabel = '参数配置';

    protected static ?int $navigationSort = 30;

    protected string $view = 'filament.pages.settings';

    public Collection $configs;

    public array $data = [];

    public function mount(): void
    {
        $this->configs = SystemConfigModel::query()->orderBy('sort')->get();
        foreach ($this->configs as $config) {
            $this->data[$config->name] = $config->value ?? '';
        }
    }

    public static function shouldRegisterNavigation(): bool
    {
        return auth()->user()->can('settings.config.show');
    }

    public function getTitle(): string
    {
        return '';
    }

    public function createAction(): Action
    {
        return CreateAction::make('create')
            ->label('新增配置')
            ->modalHeading('新增配置')
            ->modal()
            ->visible(fn () => auth()->user()->can('settings.config.add'))
            ->schema([
                TextInput::make('label')
                    ->label('配置名称')
                    ->placeholder('请输入配置名称')
                    ->required(),
                TextInput::make('name')
                    ->label('配置Key')
                    ->placeholder('请输入配置Key')
                    ->unique(SystemConfigModel::class)
                    ->required(),
                TextInput::make('value')
                    ->label('配置值')
                    ->placeholder('请输入配置值'),
                Select::make('group_name')
                    ->label('配置类型')
                    ->placeholder('请选择配置类型')
                    ->native(false)
                    ->options(SystemConfig::class)
                    ->required(),
                Select::make('input_type')
                    ->label('输入框类型')
                    ->native(false)
                    ->placeholder('请选择输入框类型')
                    ->options([
                        'input' => '输入框',
                        'select' => '选择框',
                        'radio' => '单选框',
                        'textarea' => '多行文本框',
                    ])
                    ->live()
                    ->required(),
                TextInput::make('desc')
                    ->placeholder('请输入配置描述')
                    ->label('配置描述'),
                Textarea::make('default_value')
                    ->label('默认值(json)')
                    ->rows(3)
                    ->required(function ($get) {
                        return in_array($get('input_type'), ['select', 'radio']);
                    })
                    ->json(),
                TextInput::make('sort')
                    ->label('排序')
                    ->numeric()
                    ->default(0)
                    ->helperText('数字越小越靠前'),
            ])
            ->action(function (array $data): void {
                SystemConfigModel::create($data);
            })
            ->createAnother(false)
            ->successNotificationTitle('创建成功');
    }

    public function save(): void
    {
        try {
            $data = $this->form->getState();

            foreach ($data as $key => $value) {
                SystemConfigModel::query()
                    ->where('name', $key)
                    ->update(['value' => $value]);
            }

            app(SystemConfigService::class)->deleteCache();
            Notification::make('success')->title('保存成功')->success()->send();
        } catch (\Exception $e) {
            Notification::make('error')->title($e->getMessage())->danger()->send();
        }
    }

    public function clearConfigCache(): void
    {
        app(SystemConfigService::class)->deleteCache();
        Notification::make('success')->title('清除成功')->success()->send();
    }

    protected function getFormStatePath(): string
    {
        return 'data';
    }

    public function getFormSchema(): array
    {
        $groups = SystemConfig::cases();
        $tabs = [];
        foreach ($groups as $group) {
            $tabs[] = Tab::make($group->getLabel())
                ->schema($this->getTabForm($group->value));
        }

        return [
            Tabs::make('Tabs')
                ->tabs($tabs),
        ];
    }

    protected function getTabForm(string $group): array
    {
        $isEdit = auth()->user()->can('settings.config.edit');
        $fields = $this->configs->where('group_name', $group)
            ->map(function ($item) use ($isEdit) {
                if ($item->input_type == 'input') {
                    return TextInput::make($item->name)
                        ->label($item->label)
                        ->disabled(fn () => ! $isEdit)
                        ->helperText($item->desc);
                }

                if ($item->input_type == 'textarea') {
                    return Textarea::make($item->name)
                        ->label($item->label)
                        ->disabled(fn () => ! $isEdit)
                        ->helperText($item->desc);
                }

                if ($item->input_type == 'select') {
                    return Select::make($item->name)
                        ->label($item->label)
                        ->options($item->default_value->toArray())
                        ->disabled(fn () => ! $isEdit)
                        ->helperText($item->desc);
                }

                if ($item->input_type == 'radio') {
                    return Radio::make($item->name)
                        ->label($item->label)
                        ->inline()
                        ->disabled(fn () => ! $isEdit)
                        ->options($item->default_value ? json_decode($item->default_value, true) : [])
                        ->helperText($item->desc);
                }

                return null;
            })
            ->filter()
            ->values();

        return $fields->isNotEmpty() ? $fields->toArray() : [];
    }
}
